import { useCallback, useState, useRef } from 'react'
import useMountedState from './useMountedState'

export default function useAsyncFn(fn) {
  const lastCallId = useRef(0)
  const [state, set] = useState<any>({ loading: false })
  const isMounted = useMountedState()
  const handleFn = useCallback(
    (...args) => {
      const callId = ++lastCallId.current
      set({ loading: true })
      return fn(...args).then(
        (value) => {
          const callback = args[args.length - 1]
          if (isMounted() && callId === lastCallId.current) {
            if (typeof callback === 'function') {
              callback()
            }
            set({ value, loading: false })
          }
          return value
        },
        (error) => {
          if (isMounted() && callId === lastCallId.current) {
            set({ error, loading: false })
          }
          return null
        },
      )
    },
    [fn],
  )

  return [state, handleFn]
}
